package com.mi.rof.engineer.controller;


import com.alibaba.fastjson.JSON;
import com.mi.rof.engineer.entity.*;
import com.mi.rof.engineer.mapper.InventoryMapper;
import com.mi.rof.engineer.service.EngineerService;
import com.mi.rof.engineer.service.RepairOrderService;
import com.mi.rof.engineer.service.RepairOrderStateService;
import com.mi.rof.engineer.utils.QiniuUtils;
import com.mi.rof.entity.*;
import com.mi.rof.entity.enums.ExceptionEnum;
import com.mi.rof.entity.enums.PaymentStateEnum;
import com.mi.rof.entity.enums.RepairOrderEnum;
import com.mi.rof.entity.vo.UserInfoVo;
import com.mi.rof.utils.RocketMQTopic;
import com.mi.rof.utils.UserThreadLocal;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.http.MediaType;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.io.IOException;
import java.util.UUID;
/**
 * @author zwq
 */
@RestController
@Slf4j
@Transactional(rollbackFor = Exception.class)
@RequestMapping("/repairOrder")
public class RepairOrderController {

    @Resource
    private RepairOrderService repairOrderService;

    @Resource
    private RepairOrderStateService repairOrderStateService;

    @Resource
    private EngineerService engineerService;

    @Resource
    private RocketMQTemplate rocketMqTemplate;

    private  static final Integer MIN_IMG_NUM = 3;

    @Resource
    private InventoryMapper inventoryMapper;

    private static final BigDecimal COST_RATE  =BigDecimal.valueOf(1.2);

    private static final BigDecimal HANDWORK_COST  =BigDecimal.valueOf(50);

    /**
     * 工程师上传图片和故障描述信息
     * @return Result 返回结果
     */
    @PostMapping(value = "/userConfirm",consumes = {MediaType.MULTIPART_FORM_DATA_VALUE},headers = "content-type=multipart/form-data")
    @ApiOperation("用户确认上传多张图片文件及描述信息")
    public Result<String> uploadDescAndImages(@RequestParam String uploadInfoString,  @RequestPart(value = "files") MultipartFile[] files)  {
        UserInfoVo userInfoVo = UserThreadLocal.get();
        // 判断是否有工程师权限
        Result<String> result = engineerService.checkEngineerAuth(userInfoVo);
        if(!Result.SUCCESS.equals(result.getCode())){
            throw new SystemException(ExceptionEnum.NO_AUTH.getCode(), ExceptionEnum.NO_AUTH.getMsg());
        }

        UploadInfoDTO uploadInfoDTO = JSON.parseObject(uploadInfoString,UploadInfoDTO.class);

        if (files.length < MIN_IMG_NUM) {
            return Result.fail(ExceptionEnum.IMAGE_NEED_THREE.getCode(), ExceptionEnum.IMAGE_NEED_THREE.getMsg());
        }
        // minio 上传图片
        boolean confirmedState = uploadInfoDTO.isOrderConfirmed();
        RepairOrder repairOrder=new RepairOrder();
        BeanUtils.copyProperties(uploadInfoDTO,repairOrder);
        repairOrder.setEngineerId(userInfoVo.getUserId());
        // 从工单待确认到现场确认 同步进行状态机的分支处理 工程师现场确认的分支
        repairOrderStateService.uploadFaultInfo(uploadInfoDTO);
        if(confirmedState) {
            //上传图片到对象存储
            String imgUrl = "";
            for (MultipartFile file : files) {
                try {
                    String suffix = getImgSuffix(file);
                    String fileName = UUID.randomUUID() + suffix;
                    QiniuUtils.upload2Qiniu(file.getBytes(), fileName);
                    imgUrl = imgUrl.concat("http://se79968as.hn-bkt.clouddn.com/"+fileName+";");
                }catch (IOException e){
                    throw new SystemException(ExceptionEnum.UPLOAD_ERROR.getCode(), ExceptionEnum.UPLOAD_ERROR.getMsg());
                }
            }
            // 更新图片路径
            repairOrder.setImageUrl(imgUrl);
            // 更新工单表
            repairOrderService.updateRepairOrder(repairOrder);
            // 状态变更
        }else {
            //设置工单状态为已撤回  更新工单表
            repairOrder.setIsDeleted(RepairOrderEnum.ORDER_WITHDRAWN.getCode());
            repairOrderService.updateRepairOrder(repairOrder);

        }
        return Result.successResult();
    }

    private static String getImgSuffix(MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        if(originalFilename==null){
            throw new SystemException(ExceptionEnum.UPLOAD_ERROR.getCode(), ExceptionEnum.UPLOAD_ERROR.getMsg());
        }
        long fileSize = file.getSize();
        if(fileSize > 2*1024*1024){
            throw new SystemException(ExceptionEnum.UPLOAD_ERROR.getCode(), ExceptionEnum.UPLOAD_ERROR.getMsg());
        }
        int lastIndex = originalFilename.lastIndexOf(".");
        return originalFilename.substring(lastIndex - 1);

    }

    /**
     * 预检 查看是否需要申请物料
     * @param skipApplyMaterials 是否跳过申请物料
     * @param repairOrderId 工单id
     * @return Result 返回结果
     */
    @PostMapping("/preview")
    @ApiOperation("工程师预检")
    public Result<String> preview(@RequestParam String skipApplyMaterials,
                          @RequestParam String repairOrderId) {
        UserInfoVo userInfoVo = UserThreadLocal.get();
        // 判断是否有工程师权限
        Result<String> result = engineerService.checkEngineerAuth(userInfoVo);
        if(!Result.SUCCESS.equals(result.getCode())){
            return result;
        }
        boolean isSkipApplyMaterials = Boolean.parseBoolean(skipApplyMaterials);
        repairOrderStateService.preview(isSkipApplyMaterials, repairOrderId);
        return Result.successResult();
    }


    @PostMapping("/applyMaterials")
    public Result<String> applyMaterials(@RequestBody InventoryApplyDTO inventoryApplyDTO) {
        UserInfoVo userInfoVo = UserThreadLocal.get();
        // 判断是否有工程师权限
        Result<String> result = engineerService.checkEngineerAuth(userInfoVo);
        if(!Result.SUCCESS.equals(result.getCode())){
            return result;
        }
        // 物料申请 远程调用
        Message<InventoryApplyDTO> message = MessageBuilder.withPayload(inventoryApplyDTO).build();
        rocketMqTemplate.send(RocketMQTopic.APPLY_MATERIALS_TOPIC, message);
        return Result.successResult();
    }

    @PostMapping("/applySuccess")
    public Result<String> applySuccess(@RequestParam String repairOrderId,@RequestParam String applyStatusString){
        UserInfoVo userInfoVo = UserThreadLocal.get();
        // 判断是否有工程师权限
        Result<String> result = engineerService.checkEngineerAuth(userInfoVo);
        if(!Result.SUCCESS.equals(result.getCode())){
            return result;
        }
        boolean applyStatus = Boolean.parseBoolean(applyStatusString);
        repairOrderStateService.materialDistribution(applyStatus, repairOrderId);
        return Result.successResult();
    }
    @PostMapping("/repair")
    public Result<String> repair(@RequestParam String repairOrderId,
                         @RequestParam String description){
        UserInfoVo userInfoVo = UserThreadLocal.get();
        // 判断是否有工程师权限
        Result<String> result = engineerService.checkEngineerAuth(userInfoVo);
        if(!Result.SUCCESS.equals(result.getCode())){
            return result;
        }
        RepairOrder repairOrderOld = repairOrderService.findRepairOrderById(repairOrderId);
        repairOrderOld.setRepairDescription(description);
        repairOrderService.updateRepairOrder(repairOrderOld);
        repairOrderStateService.repair(repairOrderId);
        return  Result.successResult();
    }

    @PostMapping("/review")
    public Result<String> review(@RequestParam String repairOrderId,
                        @RequestParam String reviewResult,
                        @RequestParam("file") MultipartFile file){
        //视频上传逻辑
        boolean reviewStatus = Boolean.parseBoolean(reviewResult);
        repairOrderStateService.review(repairOrderId,reviewStatus);
        if(reviewStatus) {
            //审核通过
            //更新工单的视频路径  并持久化到数据库
            String videoUrl ;
            String suffix = getVideoSuffix(file);
            String fileName = UUID.randomUUID() + suffix;
            try {
                QiniuUtils.upload2Qiniu(file.getBytes(), fileName);
            } catch (IOException e) {
                throw new SystemException(ExceptionEnum.UPLOAD_ERROR.getCode(), ExceptionEnum.UPLOAD_ERROR.getMsg());
            }
            videoUrl = "http://se79968as.hn-bkt.clouddn.com/"+fileName;
            RepairOrder repairOrder = new RepairOrder();
            repairOrder.setRepairOrderId(repairOrderId);
            repairOrder.setVideoUrl(videoUrl);
            // 更新工单表
            repairOrderService.updateRepairOrder(repairOrder);
        }
        else{
            //工单已回退到已确认状态 下一步查看是否需要继续申请物料
            log.info("工单已回退到已确认状态");
        }
        return Result.successResult();
    }

    private static String getVideoSuffix(MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        if(originalFilename==null){
            throw new SystemException(ExceptionEnum.UPLOAD_ERROR.getCode(), ExceptionEnum.UPLOAD_ERROR.getMsg());
        }
        long fileSize = file.getSize();
        if(fileSize > 10*1024*1024){
            throw new SystemException(ExceptionEnum.UPLOAD_ERROR.getCode(), ExceptionEnum.UPLOAD_ERROR.getMsg());
        }
        int lastIndex = originalFilename.lastIndexOf(".");
        return originalFilename.substring(lastIndex - 1);
    }

    @PostMapping("/applyPay")
    public Result<BigDecimal> applyPay(@RequestParam String repairOrderId){

        BigDecimal totalPrice = repairOrderService.calculateTotalPrice(repairOrderId);
        PaymentTable paymentTable = new PaymentTable();
        paymentTable.setRepairOrderId(repairOrderId);
        totalPrice = totalPrice.multiply(COST_RATE).add(HANDWORK_COST);
        paymentTable.setAmount(totalPrice);
        repairOrderService.insertPaymentTable(paymentTable);
        return Result.successResult(totalPrice);
    }

    @PostMapping("/paySuccess")
    public Result<String> paySuccess(@RequestParam String repairOrderId,
                             @RequestParam String payBill){
        PaymentTable paymentTableOld = repairOrderService.findPaymentTableByRepairOrderId(repairOrderId);

        paymentTableOld.setPayBill(payBill);
        paymentTableOld.setPaymentState(PaymentStateEnum.CLEARED.getCode());
        repairOrderService.updatePaymentState(paymentTableOld);
        // 更新库存申请表状态为已支付
        inventoryMapper.updateInventoryState(repairOrderId);
        repairOrderStateService.pay(repairOrderId);
        return Result.successResult();
    }

    @PostMapping("/returnToUser")
    public Result<String> returnToUser(@RequestParam String repairOrderId, @RequestParam String returnStatus){
        boolean returnStatusBoolean = Boolean.parseBoolean(returnStatus);
        if(returnStatusBoolean) {
            repairOrderStateService.returnDevice(repairOrderId);
        }
        return Result.successResult();
    }
}
